package service

import (
	"context"
	"github.com/pkg/errors"
	"gorm.io/gorm"
	"pay/api/pay"
	"pay/api/wxpay"
	"pay/internal/constant"
	"pay/internal/model"
	"pay/pkg/ecode"
	"strings"
)

// 查看微信收款账户配置列表
func (s *Service) GetWechatAccountList(ctx context.Context, req *pay.CommonPaginateRequest) (
	resp *pay.GetWechatAccountListResp, err error) {
	if err = s.downstream.CheckPermissionByRoute(ctx, req.Token, 0, "wechat"); err != nil {
		return
	}
	var configs []*model.WechatConfig
	resp = &pay.GetWechatAccountListResp{}
	if configs, resp.Total, err = s.dao.FindWechatAllConfigsByPage(
		ctx, req.Token.SgId, req.PStoreId, req.PageNo, req.PageSize); err != nil {
		return
	}
	for _, config := range configs {
		resp.Accounts = append(resp.Accounts, &pay.WechatAccountView{
			Id:            config.ID,
			Name:          config.Name,
			MerchantId:    config.MerchantId,
			PrincipalName: config.PrincipalName,
			Status:        pay.WechatAccountStatus(config.AccountStatus),
			Type:          pay.WechatAccountType(config.AccountType),
		})
	}
	return
}

// 直接创建微信收款账户（无需进件）
func (s *Service) CreateWechatAccount(ctx context.Context, req *pay.CreateWechatAccountRequest) (
	resp *pay.DefaultResp, err error) {
	if err = s.downstream.CheckPermissionByRoute(ctx, req.Token, 0, "wechat"); err != nil {
		return
	}
	if err = s.dao.Transaction(ctx, func(ctx context.Context) (err error) {
		if err = s.dao.Create(ctx, &model.WechatConfig{
			SgId:          req.Token.SgId,
			PStoreId:      req.PStoreId,
			Name:          req.Name,
			MerchantId:    req.MerchantId,
			AccountType:   uint8(req.Type),
			PrincipalName: req.PrincipalName,
			Status:        true,
			AccountStatus: uint8(pay.WechatAccountStatus_PRE_ACTIVATED),
			Operator:      req.Token.EmpId,
		}); err != nil {
			return
		}
		return
	}); err != nil {
		return
	}
	resp = &pay.DefaultResp{Status: true}
	return
}

// 编辑微信收款账户别名
func (s *Service) EditWechatAccount(ctx context.Context, req *pay.EditWechatAccountRequest) (
	resp *pay.DefaultResp, err error) {
	if err = s.downstream.CheckPermissionByRoute(ctx, req.Token, 0, "wechat"); err != nil {
		return
	}
	if err = s.dao.Transaction(ctx, func(ctx context.Context) (err error) {
		config := &model.WechatConfig{}
		if err = s.dao.LockObjectByID(ctx, config, req.Id, req.Token.SgId, req.PStoreId); err != nil {
			if errors.Cause(err) == gorm.ErrRecordNotFound {
				err = constant.ErrObjectNotExist
				return
			}
			return
		}
		config.Name = req.Name
		config.Operator = req.Token.EmpId
		if err = s.dao.Save(ctx, config); err != nil {
			return
		}
		return
	}); err != nil {
		return
	}
	resp = &pay.DefaultResp{Status: true}
	return
}

// 删除微信收款账户（基于收款账户ID）
func (s *Service) DeleteWechatAccount(ctx context.Context, req *pay.CommonObjectRequest) (
	resp *pay.DefaultResp, err error) {
	if err = s.downstream.CheckPermissionByRoute(ctx, req.Token, 0, "wechat"); err != nil {
		return
	}
	if err = s.dao.Transaction(ctx, func(ctx context.Context) (err error) {
		config := &model.WechatConfig{}
		if err = s.dao.LockObjectByID(ctx, config, req.Id, req.Token.SgId, req.PStoreId); err != nil {
			if errors.Cause(err) == gorm.ErrRecordNotFound {
				err = constant.ErrObjectNotExist
				return
			}
			return
		}
		var storeConfigs []*model.StoreConfig
		if storeConfigs, err = s.dao.FindStoreConfigsByAccountId(
			ctx, req.Id, req.Token.SgId, req.PStoreId, pay.PayType_PAY_WECHAT); err != nil {
			return
		}
		if len(storeConfigs) != 0 {
			err = ecode.AppendMessage(constant.ErrForbiddenAction, "有门店正在使用该收款账户，请先解绑再删除")
			return
		}
		config.Status = false
		config.Operator = req.Token.EmpId
		if err = s.dao.Save(ctx, config); err != nil {
			return
		}
		return
	}); err != nil {
		return
	}
	resp = &pay.DefaultResp{Status: true}
	return
}

// 创建微信进件申请单并提交进件 / 基于已有申请重新进件
func (s *Service) ApplyWechatAccount(ctx context.Context, req *pay.ApplyWechatAccountRequest) (
	resp *pay.ApplyWechatAccountResp, err error) {
	if err = s.downstream.CheckPermissionByRoute(ctx, req.Token, 0, "wechat"); err != nil {
		return
	}
	var reSubmit bool
	config := &model.WechatConfig{}
	if err = s.dao.Transaction(ctx, func(ctx context.Context) (err error) {

		// parker修改,目前针对不同的类型主体名称字段不一样
		var principalName string
		switch req.Type {
		case pay.WechatAccountType_WECHAT_PLATFORM:
			principalName = "小微_" + req.IdCardInfo.IdCardName
		case pay.WechatAccountType_WECHAT_ENTERPRISE:
			principalName = req.BizLicenseInfo.MerchantName
		case pay.WechatAccountType_WECHAT_INDEPENDENT:
			principalName = "个体_" + req.IdCardInfo.IdCardName
		default:
			err = ecode.AppendMessage(constant.ErrInvalidArgument, "子商户进件主体类型不支持")
			return
		}

		if req.Id == 0 {
			// 首次进件
			config = &model.WechatConfig{
				SgId:          req.Token.SgId,
				PStoreId:      req.PStoreId,
				Name:          req.MerchantShortname,
				AccountType:   uint8(req.Type),
				PrincipalName: principalName,
				AccountStatus: uint8(pay.WechatAccountStatus_WECHAT_STATUS_INIT),
				Operator:      req.Token.EmpId,
				Status:        true,
			}
			if err = s.dao.Create(ctx, config); err != nil {
				return
			}
		} else {
			if err = s.dao.LockObjectByID(ctx, config, req.Id, req.Token.SgId, req.PStoreId); err != nil {
				if errors.Cause(err) == gorm.ErrRecordNotFound {
					err = constant.ErrObjectNotExist
					return
				}
				return
			} else {
				switch pay.WechatAccountStatus(config.AccountStatus) {
				case pay.WechatAccountStatus_FINISH:
					err = ecode.AppendMessage(constant.ErrForbiddenAction, "账户已经进件完成，不需要重复申请")
					return
				case pay.WechatAccountStatus_FROZEN:
					err = ecode.AppendMessage(constant.ErrForbiddenAction, "账户已被微信冻结，不允许再次申请进件")
					return
				case pay.WechatAccountStatus_WECHAT_STATUS_INIT, pay.WechatAccountStatus_REJECTED:
					// 重新发起进件
					config.AccountType = uint8(req.Type)
					config.AccountStatus = uint8(pay.WechatAccountStatus_WECHAT_STATUS_INIT)
					config.PrincipalName = principalName
					config.Operator = req.Token.EmpId
					if err = s.dao.Save(ctx, config); err != nil {
						return
					}
					reSubmit = true
				default:
					err = ecode.AppendMessage(constant.ErrForbiddenAction, "账户进件流程进行中，不允许重新发起申请")
					return
				}
			}
		}
		return
	}); err != nil {
		return
	}
	resp = &pay.ApplyWechatAccountResp{}
	if resp.ApplyResult, err = s.downstream.WechatApply(ctx, req, config, reSubmit); err != nil {
		return
	}
	if err = s.dao.Transaction(ctx, func(ctx context.Context) (err error) {
		if err = s.dao.LockObjectByID(ctx, config, config.ID, req.Token.SgId, req.PStoreId); err != nil {
			return
		}
		config.AccountStatus = uint8(pay.WechatAccountStatus_CHECKING)
		config.ApplyNo = resp.ApplyResult.ApplyNo
		if err = s.dao.Save(ctx, config); err != nil {
			return
		}
		return
	}); err != nil {
		return
	}
	resp.AccountInfo = &pay.WechatAccountView{
		Id:            config.ID,
		Name:          config.Name,
		MerchantId:    config.MerchantId,
		PrincipalName: config.PrincipalName,
		Status:        pay.WechatAccountStatus(config.AccountStatus),
		Type:          pay.WechatAccountType(config.AccountType),
	}
	return
}

// 查看微信进件详细信息（基于收款账户ID）
func (s *Service) QueryWechatAccountApply(ctx context.Context, req *pay.CommonObjectRequest) (
	resp *pay.QueryWechatAccountApplyResp, err error) {
	if err = s.downstream.CheckPermissionByRoute(ctx, req.Token, 0, "wechat"); err != nil {
		return
	}
	config := &model.WechatConfig{}
	resp = &pay.QueryWechatAccountApplyResp{}
	if err = s.dao.Transaction(ctx, func(ctx context.Context) (err error) {
		if err = s.dao.LockObjectByID(ctx, config, req.Id, req.Token.SgId, req.PStoreId); err != nil {
			if errors.Cause(err) == gorm.ErrRecordNotFound {
				err = constant.ErrObjectNotExist
				return
			}
			return
		}
		if config.ApplyNo == "" {
			err = ecode.AppendMessage(constant.ErrNeedRefresh, "尚未发起进件，不能查询")
			return
		}

		if resp.QueryResult, err = s.downstream.QueryWechatApply(
			ctx, config.ApplyNo, req.Token.SgId, false); err != nil {
			return
		}
		// 需要触发同步
		targetStatus := pay.WechatAccountStatus(pay.WechatAccountStatus_value[resp.QueryResult.ApplyState])
		if targetStatus != pay.WechatAccountStatus(config.AccountStatus) {
			if targetStatus == pay.WechatAccountStatus_FINISH && pay.WechatAccountStatus(
				config.AccountStatus) != pay.WechatAccountStatus_FINISH {
				// 进件完成时，更新子商户号，标为待激活，触发审核邮件
				config.MerchantId = strings.Trim(resp.QueryResult.SubMchId, " ")
				config.AccountStatus = uint8(pay.WechatAccountStatus_PRE_ACTIVATED)
			} else {
				config.AccountStatus = uint8(targetStatus)
			}
			if err = s.dao.Save(ctx, config); err != nil {
				return
			}
		}
		return
	}); err != nil {
		return
	}
	resp.AccountInfo = &pay.WechatAccountView{
		Id:            config.ID,
		Name:          config.Name,
		MerchantId:    config.MerchantId,
		PrincipalName: config.PrincipalName,
		Status:        pay.WechatAccountStatus(config.AccountStatus),
		Type:          pay.WechatAccountType(config.AccountType),
	}
	return
}

// 微信专用上传图片
func (s *Service) UploadWechatImage(ctx context.Context, req *pay.UploadImageRequest) (
	resp *wxpay.GetWechatMediaIdReply, err error) {
	if err = s.downstream.CheckAdmin(ctx, req.Token, req.PStoreId); err != nil {
		return
	}
	if resp, err = s.downstream.UploadWechatImage(
		ctx, model.BootInfo.WechatServiceProviderMerchantId, req.ImageUrl); err != nil {
		return
	}
	return
}

// 激活微信收款账户
func (s *Service) ActivateWechatAccount(ctx context.Context, req *pay.ActivateWechatAccountReq) (
	resp *pay.DefaultResp, err error) {
	config := &model.WechatConfig{}
	if err = s.dao.Transaction(ctx, func(ctx context.Context) (err error) {
		if err = s.dao.LockObjectByID(ctx, config, req.Id, req.SgId, req.PStoreId); err != nil {
			if errors.Cause(err) == gorm.ErrRecordNotFound {
				err = constant.ErrObjectNotExist
				return
			}
			return
		}
		if pay.WechatAccountStatus(config.AccountStatus) != pay.WechatAccountStatus_PRE_ACTIVATED {
			err = ecode.AppendMessage(constant.ErrNeedRefresh, "收款账户状态已变更，无需重复配置")
		}
		config.AccountStatus = uint8(pay.WechatAccountStatus_FINISH)
		if err = s.dao.Save(ctx, config); err != nil {
			return
		}
		return
	}); err != nil {
		return
	}
	resp = &pay.DefaultResp{Status: true}
	return
}
